package transforms;
import java.util.Iterator;

import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.MethodNode;

import com.rshacking.rhf.files.ClassContainer;
import com.rshacking.rhf.unification.InstructionItem;
import com.rshacking.rhf.updater.Transform;
import com.rshacking.rhf.updater.hooks.ClassHook;
import com.rshacking.rhf.updater.hooks.HooksList;
import com.rshacking.rhf.updater.instructions.InsnCondition;
import com.rshacking.rhf.updater.instructions.InstructionFinder;
import com.rshacking.rhf.updater.instructions.RegexInsnFinder;

public class ClientTransforms extends Transform {

	@Override
	public boolean canActivate(final HooksList hooks, final ClassContainer cc) {
		return cc.getName().equals("client");
	}

	@Override
	public boolean execute(final HooksList hooks, final ClassContainer cc) {
		ClassHook c = null;
		if (hooks.contains("Client")) {
            c = hooks.get("Client");
        } else {
            c = hooks.add("Client", "client");
        }

		final Iterator<MethodNode> methods = cc.getASM().methods.iterator();
		while (methods.hasNext()) {
			final MethodNode method = methods.next();
			final InstructionFinder<AbstractInsnNode> finder =
				new InstructionFinder<AbstractInsnNode>(method, true);
			
			if (method.desc.equals("(I)Ljava/lang/String;")) {
				FieldInsnNode fin = null;

				fin = (FieldInsnNode) finder
						.getNext(InsnCondition.ASM.GETSTATIC_L);

				if (fin != null) {
					c.add("localPlayer", fin);
				}
				if (!hooks.contains("Player")) {
				    hooks.add("Player", fin.desc);
				}

				//finder.reset(true);
				//finder.getNext(InsnCondition.ASM.makeLDCCond("[1)"));

				fin = (FieldInsnNode) finder
                .getNext(InsnCondition.ASM.GETFIELD_IA);
				/*if (fin != null) {
                    c.add("charXLocs", fin);
                }*/
				
				fin = (FieldInsnNode) finder
						.getNext(InsnCondition.ASM.GETSTATIC_I);
				if (fin != null) {
					c.add("baseX", fin);
				}
				
				//fin = (FieldInsnNode) finder
                //.getNext(InsnCondition.ASM.GETFIELD_IA);
                /*if (fin != null) {
                    c.add("charYLocs", fin);
                }*/

				fin = (FieldInsnNode) finder
						.getNext(InsnCondition.ASM.GETSTATIC_I);
				if (fin != null) {
					c.add("baseY", fin);
				}

				finder.getNext(InsnCondition.ASM.makeIntCond(BIPUSH, 73));
				fin = (FieldInsnNode) finder
						.getNext(InsnCondition.ASM.GETSTATIC_I);
				if (fin != null) {
					c.add("loginIndex", fin); // TODO check
				}
			}
			/*else if (finder.getNext(InsnCondition.ASM.makeLDCCond("Jagex")) != null) {
				final FieldInsnNode fin = (FieldInsnNode) finder.getNext(InsnCondition.ASM.PUTSTATIC_SAA);
				if (fin != null) {
					hooks.add("ObjectData", fin.owner);
				}
			}*/
			else if (finder.getNext(InsnCondition.ASM.makeIntCond(BIPUSH, 46)) != null) {
			    final FieldInsnNode fin = (FieldInsnNode) finder.getNext(InsnCondition.ASM.makeFieldCond(INVOKESTATIC, "(I)V"));
			    if (fin != null) {
			        c.add("mouse", fin);
			    }
			}
			else if (finder.getNext(InsnCondition.ASM.makeLDCCond("canvas")) != null) {
				
				
				FieldInsnNode fin = null;

				fin = (FieldInsnNode) finder
						.getNext(InsnCondition.ASM.PUTSTATIC_L);

				if (fin != null) {
					c.add("canvas", fin);
				}
			}
			else if (finder.getNext(InsnCondition.ASM.makeLDCCond("client.MA(")) != null) {
			    // FIXME unstable ldc cond
			    
			    
			    finder.reset(true);
			    final FieldInsnNode fin = (FieldInsnNode) finder.getNext(InsnCondition.ASM.GETSTATIC_LA);
			    if (fin != null) {
			        c.add("npcNodes", fin);
			        hooks.add("NpcNode", fin.desc);
			    }
			    // pretty damn unstable cond
			}
			/*else if (method.desc.equals("(I)V")) {
				
				
				FieldInsnNode fin = null;
				
				finder.reset(false);

				fin = (FieldInsnNode) finder
						.getPrev(InsnCondition.ASM.GETFIELD_I);

				if (fin != null) {
					hooks.add("Character", fin.owner);
				}
			}*/
		}
		return true;
	}
}